home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Dev / Oberon / source / Library / Lists.mod < prev    next >
Text File  |  1995-06-29  |  7KB  |  306 lines

  1. (***************************************************************************
  2.  
  3.      $RCSfile: Lists.mod $
  4.   Description: Doubly-linked lists similar to Exec lists
  5.  
  6.    Created by: fjc (Frank Copeland)
  7.     $Revision: 1.11 $
  8.       $Author: fjc $
  9.         $Date: 1995/06/04 23:22:41 $
  10.  
  11.   Copyright © 1994-1995, Frank Copeland.
  12.   This file is part of the Oberon-A Library.
  13.   See Oberon-A.doc for conditions of use and distribution.
  14.  
  15. ***************************************************************************)
  16.  
  17. MODULE Lists;
  18.  
  19. IMPORT SYS := SYSTEM, Errors, Strings, Strings2;
  20.  
  21. TYPE
  22.  
  23.   (* A simple doubly linked node *)
  24.  
  25.   NodePtr * = POINTER TO Node;
  26.   Node * = RECORD
  27.     succ * : NodePtr;
  28.     pred * : NodePtr;
  29.   END; (* Node *)
  30.  
  31.   (* An named node. *)
  32.  
  33.   NameNodePtr * = POINTER TO NameNode;
  34.   NameNode * = RECORD (Node)
  35.     name - : POINTER TO ARRAY OF CHAR;
  36.   END; (* NameNode *)
  37.  
  38.   (* An node with a key *)
  39.  
  40.   KeyNodePtr * = POINTER TO KeyNode;
  41.   KeyNode * = RECORD (Node)
  42.     key *  : LONGINT;
  43.   END; (* KeyNode *)
  44.  
  45.   (* A list header *)
  46.  
  47.   ListPtr * = POINTER TO List;
  48.   List * = RECORD
  49.     head * : NodePtr;
  50.     tail * : NodePtr;
  51.   END; (* List *)
  52.  
  53.   (* A header for a list of NameNodes *)
  54.  
  55.   NameListPtr * = POINTER TO NameList;
  56.   NameList * = RECORD (List) END;
  57.  
  58.   (* A header for a list of KeyNodes *)
  59.  
  60.   KeyListPtr * = POINTER TO KeyList;
  61.   KeyList * = RECORD (List) END;
  62.  
  63. (* --- NameNode procedures ----------------------------------------------- *)
  64.  
  65.  
  66. (*------------------------------------*)
  67. PROCEDURE (VAR node : NameNode) Name * (name : ARRAY OF CHAR);
  68.  
  69. <*$CopyArrays-*>
  70. BEGIN (* Name *)
  71.   NEW (node.name, Strings.Length (name) + 1);
  72.   COPY (name, node.name^)
  73. END Name;
  74.  
  75.  
  76. (* --- List procedures -------------------------------------------------- *)
  77.  
  78.  
  79. (*------------------------------------*)
  80. PROCEDURE (VAR list : List) NewList*;
  81.  
  82. BEGIN (* NewList *)
  83.   list.head := NIL; list.tail := NIL
  84. END NewList;
  85.  
  86. (*------------------------------------*)
  87. PROCEDURE (VAR list : List)  AddHead * (node : NodePtr);
  88.  
  89. BEGIN (* AddHead *)
  90.   node.succ := list.head; node.pred := NIL;
  91.   IF list.head # NIL THEN list.head.pred := node END;
  92.   list.head := node;
  93.   IF list.tail = NIL THEN list.tail := node END
  94. END AddHead;
  95.  
  96. (*------------------------------------*)
  97. PROCEDURE (VAR list : List)  AddTail * (node : NodePtr);
  98.  
  99. BEGIN (* AddTail *)
  100.   node.succ := NIL; node.pred := list.tail;
  101.   IF list.tail # NIL THEN list.tail.succ := node END;
  102.   list.tail := node;
  103.   IF list.head = NIL THEN list.head := node END
  104. END AddTail;
  105.  
  106. (*------------------------------------*)
  107. PROCEDURE (VAR list : List)  Insert * (node, prevNode : NodePtr);
  108.  
  109. BEGIN (* Insert *)
  110.   IF prevNode = NIL THEN list.AddHead (node)
  111.   ELSIF prevNode = list.tail THEN list.AddTail (node)
  112.   ELSE
  113.     node.succ := prevNode.succ;
  114.     IF node.succ # NIL THEN node.succ.pred := node END;
  115.     node.pred := prevNode; prevNode.succ := node
  116.   END
  117. END Insert;
  118.  
  119. (*------------------------------------*)
  120. PROCEDURE (VAR list : List)  IsListEmpty * () : BOOLEAN;
  121.  
  122. BEGIN (* IsListEmpty *)
  123.   RETURN (list.head = NIL)
  124. END IsListEmpty;
  125.  
  126.  
  127. (*------------------------------------*)
  128. PROCEDURE (VAR list : List)  RemHead * () : NodePtr;
  129.  
  130.   VAR node : NodePtr;
  131.  
  132. BEGIN (* RemHead *)
  133.   node := list.head;
  134.   IF node # NIL THEN
  135.     list.head := node.succ;
  136.     IF list.tail = node THEN list.tail := NIL END;
  137.     node.pred := NIL; node.succ := NIL
  138.   END;
  139.   RETURN node
  140. END RemHead;
  141.  
  142. (*------------------------------------*)
  143. PROCEDURE (VAR list : List)  RemTail * () : NodePtr;
  144.  
  145.   VAR node : NodePtr;
  146.  
  147. BEGIN (* RemTail *)
  148.   node := list.tail;
  149.   IF node # NIL THEN
  150.     list.tail := node.pred;
  151.     IF list.head = node THEN list.head := NIL END;
  152.     node.pred := NIL; node.succ := NIL
  153.   END;
  154.   RETURN node
  155. END RemTail;
  156.  
  157.  
  158. (*------------------------------------*)
  159. PROCEDURE (VAR list : List)  Remove * (node : NodePtr);
  160.  
  161. BEGIN (* Remove *)
  162.   IF node.succ # NIL THEN node.succ.pred := node.pred END;
  163.   IF node.pred # NIL THEN node.pred.succ := node.succ END;
  164.   IF list.head = node THEN list.head := node.succ END;
  165.   IF list.tail = node THEN list.tail := node.pred END;
  166.   node.succ := NIL; node.pred := NIL
  167. END Remove;
  168.  
  169.  
  170. (*------------------------------------*)
  171. PROCEDURE (VAR list : List) Enqueue * (node : NodePtr);
  172.  
  173. BEGIN (* Enqueue *)
  174.   HALT (Errors.notImplemented)
  175. END Enqueue;
  176.  
  177. (* --- List procedures requiring NameNodes ------------------------------- *)
  178.  
  179.  
  180. (*------------------------------------*)
  181. PROCEDURE (VAR list : NameList) AddHead * (node : NodePtr);
  182.  
  183. BEGIN (* AddHead *)
  184.   WITH node : NameNodePtr DO list.AddHead^ (node) END
  185. END AddHead;
  186.  
  187. (*------------------------------------*)
  188. PROCEDURE (VAR list : NameList) AddTail * (node : NodePtr);
  189.  
  190. BEGIN (* AddTail *)
  191.   WITH node : NameNodePtr DO list.AddTail^ (node) END
  192. END AddTail;
  193.  
  194. (*------------------------------------*)
  195. PROCEDURE (VAR list : NameList) Insert * (node, prevNode : NodePtr);
  196.  
  197. BEGIN (* Insert *)
  198.   WITH node : NameNodePtr DO list.Insert^ (node, prevNode) END
  199. END Insert;
  200.  
  201. (*------------------------------------*)
  202. PROCEDURE (VAR list : NameList) Enqueue * (node : NodePtr);
  203.  
  204.   VAR next : NodePtr;
  205.  
  206. BEGIN (* Enqueue *)
  207.   WITH node : NameNodePtr DO
  208.     next := list.head;
  209.     WHILE (next # NIL) & (next(NameNodePtr).name^ <= node.name^) DO
  210.       next := next.succ
  211.     END;
  212.     IF next = NIL THEN list.AddTail (node)
  213.     ELSE list.Insert (node, next.pred)
  214.     END
  215.   END;
  216. END Enqueue;
  217.  
  218. (*------------------------------------*)
  219. PROCEDURE (VAR list : NameList) Find *
  220.   (name : ARRAY OF CHAR) : NodePtr;
  221.  
  222.   VAR next : NodePtr;
  223.  
  224. <*$CopyArrays-*>
  225. BEGIN (* Find *)
  226.   next := list.head;
  227.   WHILE (next # NIL) & (next(NameNodePtr).name^ # name) DO
  228.     next := next.succ
  229.   END;
  230.   RETURN next
  231. END Find;
  232.  
  233. (*------------------------------------*)
  234. PROCEDURE (VAR list : NameList) FindCap *
  235.   (name : ARRAY OF CHAR) : NodePtr;
  236.  
  237.   VAR next : NodePtr;
  238.  
  239. <*$CopyArrays-*>
  240. BEGIN (* FindCap *)
  241.   next := list.head;
  242.   WHILE
  243.     (next # NIL) & (Strings2.CompareCAP (next(NameNodePtr).name^, name) # 0)
  244.   DO
  245.     next := next.succ
  246.   END;
  247.   RETURN next
  248. END FindCap;
  249.  
  250.  
  251. (* --- List procedures requiring KeyNodes ------------------------------- *)
  252.  
  253. (*------------------------------------*)
  254. PROCEDURE (VAR list : KeyList)  AddHead * (node : NodePtr);
  255.  
  256. BEGIN (* AddHead *)
  257.   WITH node : KeyNodePtr DO list.AddHead^ (node) END
  258. END AddHead;
  259.  
  260. (*------------------------------------*)
  261. PROCEDURE (VAR list : KeyList)  AddTail * (node : NodePtr);
  262.  
  263. BEGIN (* AddTail *)
  264.   WITH node : KeyNodePtr DO list.AddTail^ (node) END
  265. END AddTail;
  266.  
  267. (*------------------------------------*)
  268. PROCEDURE (VAR list : KeyList)  Insert * (node, prevNode : NodePtr);
  269.  
  270. BEGIN (* Insert *)
  271.   WITH node : KeyNodePtr DO list.Insert^ (node, prevNode) END
  272. END Insert;
  273.  
  274. (*------------------------------------*)
  275. PROCEDURE (VAR list : KeyList) Enqueue * (node : NodePtr);
  276.  
  277.   VAR next : NodePtr;
  278.  
  279. BEGIN (* Enqueue *)
  280.   WITH node : KeyNodePtr DO
  281.     next := list.head;
  282.     WHILE (next # NIL) & (next(KeyNodePtr).key <= node.key) DO
  283.       next := next.succ
  284.     END;
  285.     IF next = NIL THEN list.AddTail (node)
  286.     ELSE list.Insert (node, next.pred)
  287.     END
  288.   END;
  289. END Enqueue;
  290.  
  291. (*------------------------------------*)
  292. PROCEDURE (VAR list : KeyList) Find * (key : LONGINT) : NodePtr;
  293.  
  294.   VAR next : NodePtr;
  295.  
  296. <*$CopyArrays-*>
  297. BEGIN (* Find *)
  298.   next := list.head;
  299.   WHILE (next # NIL) & (next(KeyNodePtr).key # key) DO
  300.     next := next.succ
  301.   END;
  302.   RETURN next
  303. END Find;
  304.  
  305. END Lists.
  306.